﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using Controller2.BLL;
using Controller2.Models;
using Controller2.Models.ViewModels;
using Controller2.Models.Admin;
using Telerik.Web.Mvc;
using System.Security.Principal;
using Controller2.Services.Admin;

namespace Controller2.Controllers
{
    public class AccountController : Controller
    {
        ControllerBDModelContainer db = new ControllerBDModelContainer();
        AccountViewModel viewModel = new AccountViewModel();
        
        public IFormsAuthentication FormsAuth { get; private set; }
        public IMembershipService MembershipService { get; private set; }
        public IRoleService RoleService { get; private set; }

        // This constructor is used by the MVC framework to instantiate the controller using
        // the default forms authentication and membership providers.
        public AccountController()
            : this(null, null, null)
        {
        }

        // This constructor is not used by the MVC framework but is instead provided for ease
		// of unit testing this type. See the comments at the end of this file for more
		// information.
        public AccountController(IFormsAuthentication formsAuth, IMembershipService membershipService, IRoleService roleService)
		{
			FormsAuth = formsAuth ?? new FormsAuthenticationService();
            MembershipService = membershipService ?? new MembershipService();
		    RoleService = roleService ?? new RoleService();
		}

        protected override void Initialize(RequestContext requestContext)
        {
            if (FormsAuth == null) { FormsAuth = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new MembershipService(); }

            base.Initialize(requestContext);
        }

        public ActionResult PrimeiroAcesso()
        {
            var model = new SenhaMaster();
            return View(model);
        }

        [HttpPost]
        public ActionResult PrimeiroAcesso(SenhaMaster model)
        {
            if (ModelState.IsValid)
            {                
                if (model.CompararSenha(model.Senha))
                {
                    if (!RoleService.RoleExists("SysAdmin"))
                    {
                        RoleService.CreateRole("SysAdmin");
                    }
                    MembershipCreateStatus createStatus = MembershipService.CreateUser("masterAdmin", model.Senha, model.Email);

                    if (createStatus == MembershipCreateStatus.Success)
                    {
                        RoleService.CreateRole("Administrador");
                        RoleService.CreateRole("Cliente");
                        RoleService.CreateRole("DiretorArte");
                        RoleService.CreateRole("Funcionario");
                        RoleService.CreateRole("Gerente");
                        RoleService.RemoveUserFromRole("masterAdmin", "Admin");
                        RoleService.DeleteRole("Admin", true);                        

                        Roles.AddUserToRole("masterAdmin", "SysAdmin");                        
                        
                        FormsAuth.SignIn("masterAdmin", false /* createPersistentCookie */);
                        Session["Msg"] = "Usuário com privilégio de Administrador Geral do Sistema (SysAdmin) criado com sucesso! Seja bem-vindo " + User.Identity.Name;
                        return RedirectToAction("Index", "Home");
                    }
                    else
                    {
                        ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
                    }
                }
                else
                {
                    ModelState.AddModelError("Senha", "* A Senha Master não confere com a senha digitada!");
                }
            }
            return View(model);
        }

        // **************************************
        // URL: /Account/LogIn
        // **************************************

        public ActionResult LogIn()
        {
            if (Membership.GetAllUsers().Count == 0)
            {
                return RedirectToAction("PrimeiroAcesso");
            }
            return View();
        }

        [HttpPost]
        public ActionResult LogIn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ValidateUser(model.UserName, model.Password))
                {
                    FormsAuth.SignIn(model.UserName, model.RememberMe);
                    if (Url.IsLocalUrl(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "- O nome de usuário ou a senha está incorreto.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        // **************************************
        // URL: /Account/LogOff
        // **************************************

        public ActionResult LogOff()
        {
            FormsAuth.SignOut();

            return RedirectToAction("Index", "Home");
        }

        // **************************************
        // URL: /Account/Register
        // **************************************
                
        //public ActionResult Registrar()
        //{
        //    if (Membership.GetAllUsers().Count == 0)
        //    {
        //        ViewBag.PasswordLength = MembershipService.MinPasswordLength;
        //        return View();
        //    }
        //    else
        //    {
        //        Session["Msg"] = "Desculpe, mas você não tem privilégios para criar seu próprio usuário.";
        //        return RedirectToAction("Index", "Home");
        //    }
        //}
                
        //[HttpPost]
        //public ActionResult Registrar(RegisterModel model)
        //{
        //    if (Membership.GetAllUsers().Count == 0)
        //    {
        //        if (ModelState.IsValid)
        //        {
        //            MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);

        //            if (createStatus == MembershipCreateStatus.Success)
        //            {
        //                RoleService.CreateRole("Administrador");
        //                RoleService.CreateRole("Cliente");
        //                RoleService.CreateRole("DiretorArte");
        //                RoleService.CreateRole("Funcionario");
        //                RoleService.CreateRole("Gerente");
        //                RoleService.CreateRole("SysAdmin");
        //                Roles.AddUserToRole(model.UserName, "SysAdmin");
        //                FormsAuth.SignIn(model.UserName, false /* createPersistentCookie */);
        //                Session["MsgErro"] = "Usuário com privilégio de Administrador Geral do Sistema (SysAdmin) criado com sucesso! Seja bem-vindo " + User.Identity.Name;
        //                return RedirectToAction("Index", "Home");
        //            }
        //            else
        //            {
        //                ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
        //            }
        //        }

        //        // If we got this far, something failed, redisplay form
        //        ViewBag.PasswordLength = MembershipService.MinPasswordLength;
        //        return View(model);
        //    }
        //    else
        //    {
        //        Session["Msg"] = "Desculpe, mas você não tem privilégios para criar seu próprio usuário.";
        //        return RedirectToAction("Index", "Home");
        //    }
        //}

        // **************************************
        // URL: /Account/ChangePassword
        // **************************************

        [Authorize(Roles = "SysAdmin")]
        public ActionResult ChangePassword()
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize(Roles = "SysAdmin")]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "A senha atual está incorreta ou a nova senha é inválida!");
                }
            }

            // If we got this far, something failed, redisplay form
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePasswordSuccess
        // **************************************

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

        [Authorize(Roles = "SysAdmin")]
        public ActionResult Index()
        {
            //ViewBag.IsInRole = User.IsInRole("SysAdmin") ? true : false;
            //var dic = new Dictionary<string, int>();
            //dic.Add("Nome de Usuário", 1);
            //dic.Add("Nome", 2);
            //ViewBag.Pesquisa = PesquisaBll.PreencheComboPesquisa(dic, "Consulta Contas Usuários: ");
            //Session["texto"] = "";
            //Session["filtro"] = 0;
            //return View();
            return RedirectToAction("Admin");
        }

        //[Authorize(Roles = "SysAdmin")]
        //[GridAction]
        //public ActionResult AjaxGrid()
        //{
        //    var users = new GridModel { Data = viewModel.Listar(db) };
        //    return View(users);
        //}

        [Authorize(Roles = "SysAdmin, Administrador, Gerente, DiretorArte")]
        public ActionResult IncluirUsuario(int id, string request, string email, string tipoFunc = "")
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            Session["IdPessoa"] = id;
            ViewBag.Request = Session["Request"] = request;
            if (!string.IsNullOrWhiteSpace(tipoFunc))
            {
                Session["TipoFuncionario"] = tipoFunc;
            }
            ViewBag.Email = email;
            return View();
        }

        [Authorize(Roles = "SysAdmin, Administrador, Gerente, DiretorArte")]
        [HttpPost]
        public ActionResult IncluirUsuario(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Tenta cadastrar o usuário
                MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);
                string role;
                var request = Session["Request"].ToString();
                var tipoFunc = Session["TipoFuncionario"] != null ? Session["TipoFuncionario"].ToString() : null;
                if (tipoFunc != null)
                {
                    role = tipoFunc.Equals("Freelancer") ? "Funcionario" : tipoFunc;
                }
                else
                {
                    role = request;
                }
                if (createStatus == MembershipCreateStatus.Success)
                {
                    try
                    {
                        if (model.Role == null || model.Role.Equals(""))
                        {
                            Roles.AddUserToRole(model.UserName, role);
                            // inclui o nome de usuário na Pessoa
                            var id = Convert.ToInt32(Session["IdPessoa"]);
                            var pessoa = db.Pessoa.Where(p => p.IdPessoa == id).FirstOrDefault();
                            pessoa.UserName = model.UserName;
                            db.Pessoa.ApplyCurrentValues(pessoa);
                            db.SaveChanges();
                        }
                        else
                        {
                            Roles.AddUserToRole(model.UserName, model.Role);
                        }
                        Session["Request"] = null;
                        Session["TipoFuncionario"] = null;
                        switch (request)
                        {
                            default: return RedirectToAction("Index", "Home");
                            case "Cliente": return RedirectToAction("Index", "Cliente");
                            case "Funcionario": return RedirectToAction("Index", "Funcionario");
                            case "Novo": return RedirectToAction("Index", "Account");
                        }
                    }
                    catch (Exception ex)
                    {
                        Roles.RemoveUserFromRole(model.UserName, role);
                        Membership.DeleteUser(model.UserName);
                        string msgEx;
                        if (ex.InnerException == null)
                        {
                            msgEx = ex.Message;
                        }
                        else
                        {
                            msgEx = ex.InnerException.Message;
                        }
                        ModelState.AddModelError("", msgEx);
                        return View(model);
                    }
                }
                else
                {
                    ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
                }
            }

            // Se chegar aqui, é porque teve erros, então mostramos novamente o formulário
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View(model);
        }

        [Authorize]
        public ActionResult AlterarSenha()
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult AlterarSenha(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                    {
                        return RedirectToAction("AlterarSenhaSucesso", "Account");
                    }
                    else
                    {
                        ModelState.AddModelError("", "A senha atual está incorreta ou a nova senha é inválida!");
                    }
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError(string.Empty, ex);
                    ViewBag.PasswordLength = MembershipService.MinPasswordLength;
                    return View(model);
                }
            }
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View(model);
        }

        [Authorize]
        public ActionResult AlterarSenhaSucesso()
        {
            return View();
        }

        [Authorize(Roles = "SysAdmin")]
        [HttpPost]
        public ActionResult Pesquisa(string texto, int filtro)
        {
            Session["texto"] = texto;
            Session["filtro"] = filtro;
            return Json(new { salvo = true });
        }

        [Authorize(Roles = "SysAdmin")]
        [HttpPost]
        public JsonResult AutoComplete(int filtro, string termoPesquisa)
        {
            var data = AccountBll.AutoComplete(db, filtro, termoPesquisa, 10);
            return Json(data);
        }

        [Authorize(Roles = "SysAdmin, Administrador, Gerente, DiretorArte")]
        [HttpPost]
        public ActionResult ExcluirUsuario(string username)
        {
            try
            {
                var pessoa = PessoaBll.GetPessoa(db, username);
                if (Membership.DeleteUser(username))
                {
                    if (pessoa != null)
                    {
                        pessoa.UserName = "";
                        db.Pessoa.ApplyCurrentValues(pessoa);
                        db.SaveChanges();
                    }
                    return Json(new { salvo = true });
                }
                else
                {
                    var msgEx = "Não foi possível excluir o usuário.";
                    return Json(new { salvo = false, error = msgEx });
                }
            }
            catch (Exception ex)
            {
                string msgEx;
                if (ex.InnerException == null)
                {
                    msgEx = ex.Message;
                }
                else
                {
                    msgEx = ex.InnerException.Message;
                }
                return Json(new { salvo = false, error = msgEx });
            }
        }

        #region Parte de Administração de Usuários
        [Authorize(Roles = "SysAdmin")]
        public ActionResult Admin()
        {            
            AdminViewModel viewModel = new AdminViewModel
            {
                Users = MembershipService.GetAllUsers(),
                Roles = RoleService.GetAllRoles()
            };

            return View(viewModel);
        }

        [Authorize(Roles = "SysAdmin")]
        public ActionResult DeleteRole(string role)
        {
            if (RoleService.RoleExists(role))
            {
                // Cannot delete the Admin role
                //
                if (role == "Administrador")
                {
                    TempData["RoleError"] = "Impossível excluir a regra \"SysAdmin\".";
                }
                else
                {
                    // Remove the role from all users
                    //
                    try
                    {
                        string[] userNames = RoleService.GetUsersInRole(role);
                        if (userNames != null && userNames.Length > 0)
                        {
                            RoleService.RemoveUsersFromRole(userNames, role);
                        }

                        // Delete the role
                        //
                        try
                        {
                            if (!RoleService.DeleteRole(role, true))
                            {
                                TempData["RoleError"] = "Impossível excluir esta regra.";
                            }
                        }
                        catch (Exception)
                        {
                            TempData["RoleError"] = "Impossível excluir esta regra.";
                        }
                    }
                    catch (Exception)
                    {
                        TempData["RoleError"] = "Impossível excluir usuários desta regra.";
                    }
                }
            }

            return RedirectToAction("Admin");
        }

        [Authorize(Roles = "SysAdmin")]
        public ActionResult AddRole(string newRole)
        {
            if (RoleService.RoleExists(newRole))
            {
                TempData["RoleError"] = "Esta regra já existe.";
            }
            else
            {
                RoleService.CreateRole(newRole);
            }
            return RedirectToAction("Admin");
        }

        [Authorize(Roles = "SysAdmin")]
        public ActionResult ToggleRole(string role, string userName)
        {
            try
            {
                MembershipUser user = MembershipService.GetUser(userName, false);
                if (user != null)
                {
                    if (RoleService.RoleExists(role))
                    {
                        if (role == "SysAdmin" && userName == HttpContext.User.Identity.Name)
                        {
                            TempData["UserError"] = "Não é possível remover o seu próprio usuário da regra \"SysAdmin\".";
                        }
                        else
                        {
                            if (RoleService.IsUserInRole(userName, role))
                            {
                                try
                                {
                                    RoleService.RemoveUserFromRole(userName, role);
                                }
                                catch (Exception)
                                {
                                    TempData["UserError"] = "Falha ao remover o usuário desta regra.";
                                }
                            }
                            else
                            {
                                try
                                {
                                    RoleService.AddUserToRole(userName, role);
                                }
                                catch (Exception)
                                {
                                    TempData["UserError"] = "Falha ao inserir o usuário nesta regra.";
                                }
                            }
                        }
                    }
                    else
                    {
                        TempData["UserError"] = "Regra não existente.";
                    }
                }
            }
            catch (Exception)
            {
                TempData["UserError"] = "Não foi possível encontrar o usuário.";
            }
            return RedirectToAction("Admin");
        }

        [Authorize(Roles = "SysAdmin")]
        public ActionResult UnlockUser(string userName)
        {
            try
            {
                MembershipUser user = MembershipService.GetUser(userName, false);

                if (!user.UnlockUser())
                {
                    TempData["UserError"] = "Falha ao desbloquear o usuário.";
                }
            }
            catch (Exception)
            {
                TempData["UserError"] = "Não foi possível encontrar o usuário.";
            }

            return RedirectToAction("Admin");
        }

        [Authorize(Roles = "SysAdmin")]
        public ActionResult ToggleApproved(string userName)
        {
            if (userName == User.Identity.Name)
            {
                TempData["UserError"] = "Você não pode desativar a si mesmo.";
            }
            else
            {
                try
                {
                    MembershipUser user = MembershipService.GetUser(userName, false);
                    user.IsApproved = !user.IsApproved;
                    try
                    {
                        MembershipService.UpdateUser(user);
                    }
                    catch (Exception)
                    {
                        TempData["UserError"] = "Falha ao atualizar o usuário.";
                    }
                }
                catch (Exception)
                {
                    TempData["UserError"] = "Não foi possível encontrar o usuário.";
                }
            }

            return RedirectToAction("Admin");
        }

        [Authorize(Roles = "SysAdmin")]
        public ActionResult ResetPassword(string userName)
        {
            try
            {
                string password;
                if (!MembershipService.ResetPassword(userName, User.Identity.Name, out password))
                {
                    TempData["UserError"] = "Não foi possível enviar o email ao usuário. A senha deste usuário é: " + password;
                }
            }
            catch (Exception)
            {
                TempData["UserError"] = "Não foi possível encontrar o usuário.";
            }

            return RedirectToAction("Admin");
        }

        [Authorize(Roles = "SysAdmin")]
        public ActionResult DeleteUser(string userName)
        {
            if (userName == User.Identity.Name)
            {
                TempData["UserError"] = "Você não pode excluir o seu próprio nome de usuário.";
            }
            else
            {
				var pessoa = PessoaBll.GetPessoa(db, userName);
                if (!MembershipService.DeleteUser(userName, true))
                {
                    TempData["UserError"] = "Não foi possível excluir o usuário.";
                }
				else
				{
					if (pessoa != null)
					{
						pessoa.UserName = "";
						db.Pessoa.ApplyCurrentValues(pessoa);
						db.SaveChanges();
					}
				}
            }

            return RedirectToAction("Admin");
        }

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.User.Identity is WindowsIdentity)
            {
                throw new InvalidOperationException("Windows authentication is not supported.");
            }

            // Register activity for the user.
            Membership.GetUser(User.Identity.Name, true);
        }
        #endregion
    }
}
